<?php
/* this class controls all e-mails and messaging */
class email{
	private $db;

	public function __construct($dbh){
		$this->db = $dbh;
	}

	/* validates an email address and returns the result as true or false */
	public function validateEmailAddress($emailAddress){
		if(filter_var($emailAddress, FILTER_VALIDATE_EMAIL)){
			return true;
		}else{
			return false;
		}
	}

	/* validates the phone number for the international format */
	public function validatePhoneNumber($phoneNumber){
		return preg_match('/^\+([0-9]{5,20})/',$phoneNumber);
	}

	/* this method sends an e-mail to the site admin about 
		about a new comment that was posted within an article */
	public function sendNewCommentNotification($articleUrl,$articleName,
												$authorName,$authorImage,
												$commentText){
		// for security purposes capture the useragent and ip address
		$senderIp = "undefined";
		if(array_key_exists("REMOTE_ADDR", $_SERVER)){
			$senderIp = $_SERVER["REMOTE_ADDR"];
		}

		// capture the clients user agent
		$senderUserAgent = "undefined";
		if(array_key_exists("HTTP_USER_AGENT", $_SERVER)){
			$senderUserAgent = $_SERVER["HTTP_USER_AGENT"];
		}

		// define the subject of the email
		$email_subject = constant("CONFIG_EMAIL_NEWCOMMENT_SUBJECT_"
									.$this->db->getLanguageCode())
									."\"".$articleName."\"";

		// prepare the template, assign vars, generate
		$email_template = new Smarty();
		$email_template->assign("emailtype","newcomment");
		$email_template->assign("languageCode",$this->db->getLanguageCode());
		$email_template->assign("emailsubject",htmlspecialchars($email_subject));
		$email_template->assign("authorname",$authorName);
		$email_template->assign("authorimage",$authorImage);
		$email_template->assign("articleurl",$articleUrl);
		$email_template->assign("articlename",$articleName);
		$email_template->assign("commenttext",htmlspecialchars($commentText));
		$email_template->assign("ipaddress",$senderIp);
		$email_template->assign("useragent",$senderUserAgent);
		$email_template->assign("year",date("Y"));
		$email_template->assign("publishdate",date("d.m.Y H:i:s"));
		$email_template->assign("webdomain",CONFIG_CDN_PRIMARY_DOMAIN);
		$email_html = $email_template->fetch("themes/email/master.tpl");

		// send the comment notification now
		$this->sendEmailMessage(CONFIG_EMAIL_SITEADMIN,$email_subject,$email_html);	
	}

	/* this method sends a contact message to the site contact email address 
		with the data provided as parameters. It does integrity checks on the 
		email address and the phone number */
	public function sendContactRequest($senderEmail, $senderName, $senderPhone, $senderMessage){
		$result = false;

		// do the data integrity check
		if($this->validateEmailAddress($senderEmail)==true
			&&($this->validatePhoneNumber($senderPhone)==true
				||strlen($senderPhone)==0)
			&&strlen($senderName)>0&&strlen($senderMessage)>0){
			// for security purposes capture the useragent and ip address
			$senderIp = "undefined";
			if(array_key_exists("REMOTE_ADDR", $_SERVER)){
				$senderIp = $_SERVER["REMOTE_ADDR"];
			}

			// capture the clients user agent
			$senderUserAgent = "undefined";
			if(array_key_exists("HTTP_USER_AGENT", $_SERVER)){
				$senderUserAgent = $_SERVER["HTTP_USER_AGENT"];
			}

			// define the subject of the email
			$email_subject = constant("CONFIG_EMAIL_CONTACT_SUBJECT_"
								.$this->db->getLanguageCode()).$senderName;

			// prepare the template, assign vars, generate
			$email_template = new Smarty();
			$email_template->assign("emailtype","contactrequest");
			$email_template->assign("languageCode",$this->db->getLanguageCode());
			$email_template->assign("emailsubject",htmlspecialchars($email_subject));
			$email_template->assign("emailaddress",$senderEmail);
			$email_template->assign("fullname",htmlspecialchars($senderName));
			$email_template->assign("phone",$senderPhone);
			$email_template->assign("ipaddress",$senderIp);
			$email_template->assign("useragent",$senderUserAgent);
			$email_template->assign("message",htmlspecialchars($senderMessage));
			$email_template->assign("year",date("Y"));
			$email_template->assign("webdomain",CONFIG_CDN_PRIMARY_DOMAIN);
			$email_html = $email_template->fetch("themes/email/master.tpl");

			// data is valid, send the contact request email
			$this->sendEmailMessage(CONFIG_EMAIL_SITEADMIN,$email_subject,$email_html);
	
			// set the result to true
			$result = true;
		}

		return $result;		
	}

	/* sends and unsubscribe request email to the recipient 
		which contains the link to unsubscribe to this newsletter */
	public function sendUnsubscribe($recipientEmail){
		$result = false;

		// validate email and send request
		if($this->validateEmailAddress($recipientEmail)==true
			&&$this->db->isExistingSubscriber($recipientEmail)==true){
			// first get the subscriber details
			$subscriber = $this->db->getSubscriber($recipientEmail);

			// generate the unsubscribe token
			$unsubscribeToken = $this->generateUnsubscribeToken($recipientEmail);

			// prepare the unsubscribe email
			$email_subject = constant("CONFIG_EMAIL_UNSUBSCRIBE_SUBJECT_"
									.$this->db->getLanguageCode());

			// prepare the template, assign vars, generate
			$email_template = new Smarty();
			$email_template->assign("emailtype","unsubscribe");
			$email_template->assign("languageCode",$this->db->getLanguageCode());
			$email_template->assign("fullname",htmlspecialchars($subscriber["fullname"]));
			$email_template->assign("gender",$subscriber["gender"]);
			$email_template->assign("phone",$subscriber["phone"]);
			$email_template->assign("emailsubject",htmlspecialchars($email_subject));
			$email_template->assign("emailaddress",$recipientEmail);
			$email_template->assign("subscription_update",false);
			$email_template->assign("unsubscribe_token",$unsubscribeToken);
			$email_template->assign("year",date("Y"));
			$email_template->assign("webdomain",CONFIG_CDN_PRIMARY_DOMAIN);
			$email_html = $email_template->fetch("themes/email/master.tpl");

			// send the email
			$this->sendEmailMessage($recipientEmail,$email_subject,$email_html);

			// set result to true
			$result = true;
		}

		return $result;
	}

	/* sends an opt-in request to the defined e-mail 
		address asking for subscription to the 
		database. */
	public function sendOptIn($recipientEmail,$fullname="",$gender=0,$phonenumber=0){
		// define default e-mail subject
		$email_subject = constant("CONFIG_EMAIL_OPTIN_SUBJECT_"
									.$this->db->getLanguageCode());

		// define empty default unsubscribe token
		$unsubscribeToken = "";

		$isSubscriptionUpdate = false;
		if($this->db->isExistingSubscriber($recipientEmail)){
			$isSubscriptionUpdate = true;
			$unsubscribeToken = $this->generateUnsubscribeToken($recipientEmail);
			$email_subject = constant("CONFIG_EMAIL_UPDATE_SUBJECT_"
									.$this->db->getLanguageCode());
		}

		$email_template = new Smarty();
		$email_template->assign("emailtype","optin");
		$email_template->assign("languageCode",$this->db->getLanguageCode());
		$email_template->assign("fullname",htmlspecialchars($fullname));
		$email_template->assign("gender",$gender);
		$email_template->assign("phone",$phonenumber);
		$email_template->assign("optintoken",$this->generateOptinToken
				($recipientEmail,$fullname,$gender,$phonenumber));
		$email_template->assign("emailsubject",htmlspecialchars($email_subject));
		$email_template->assign("emailaddress",$recipientEmail);
		$email_template->assign("unsubscribe_token",$unsubscribeToken);
		$email_template->assign("subscription_update",$isSubscriptionUpdate);
		$email_template->assign("year",date("Y"));
		$email_template->assign("webdomain",CONFIG_CDN_PRIMARY_DOMAIN);
		$email_html = $email_template->fetch("themes/email/master.tpl");

		$this->sendEmailMessage($recipientEmail,$email_subject,$email_html);
	}

	/* decodes the optin token and returns the data */
	public function decryptOptInToken($optinToken){
		$rawObjectText = crypto::decryptText($optinToken,CONFIG_EMAIL_OPTINKEY);
		$result = json_decode($rawObjectText);

		/* verify the validity of the token */
		if($result!=""){
			if(array_key_exists("created", $result)){
				/* the created date should've been within 
					the past seven days as each token is only 
					valid for seven days maximum. */
				$tokenExpiry = (intval($result->created)+604800);
				if($tokenExpiry < time()){
					/* reset the result as token is outdated */
					$result = "";
				}else{
					$result->isSubscriptionUpdate = 0;
					if($this->db->isExistingSubscriber($result->email)){
						$result->isSubscriptionUpdate = 1;
					}

					/* update the subscription in the database */
					$this->db->updateSubscriber($result->gender,$result->fullname,
											$result->email,$result->phone);
				}
			}
		}

		return $result;
	}

	/* immediately updates the data in the database and returns 
		true when everything is ok, false when there were errors 
		in the parameters provided */
	public function updateSubscriber($gender,$fullname,$email,$phone){
		$result = false;
		if($this->validateEmailAddress($email)==true && 
			($this->validatePhoneNumber($phone)==true
				||strlen($phone)==0||intval($phone)==0)){
			// update the subscriber data in the database
			$this->db->updateSubscriber($gender,$fullname,$email,$phone);
			$result = true;
		}
		return $result;
	}

	/* this method unsubscribes an email address with 
		the unsubscribe token generated in the 
		generateUnsubscribeToken()-method */
	public function unsubscribe($unsubscribeToken){
		$result = false;

		// decrypt the unsubscribe token
		$plainToken = json_decode(crypto::decryptText($unsubscribeToken,
											CONFIG_EMAIL_OPTINKEY));

		// ensure the token is valid and set
		if($plainToken!=""&&$plainToken!=false){
			// validate the token email and signup date
			if($this->validateEmailAddress($plainToken->email)){
				// get the signup date and compare it
				$signUpDate = $this->db->getSubscriberSignupDate($plainToken->email);
				if($signUpDate!=""&&$signUpDate==$plainToken->signupdate){
					// all data matches, now remove the subscriber
					$this->db->updateSubscriber(0,"",$plainToken->email,"",false);
					$result = true;
				}
			}
		}

		return $result;
	}

	/* creates the token for unsubscription */
	private function generateUnsubscribeToken($email){
		$result = "";

		// validate the email address
		if($this->validateEmailAddress($email)){
			$signUpDate = $this->db->getSubscriberSignupDate($email);
			if($signUpDate>0){
				$result = crypto::encryptText(json_encode(array(
						"email" => $email,
						"signupdate" => $signUpDate,
						"siteid" => $this->db->getSiteId()
					)),CONFIG_EMAIL_OPTINKEY);
			}
		}

		return $result;
	}

	/* generates an optin token for authentication 
		as owner of the e-mail address*/
	private function generateOptinToken($emailAddress,$fullname="",$gender=0,$phonenumber=0){
		$rawToken = json_encode(array("email" => $emailAddress, 
								"fullname" => $fullname,
								"gender" => $gender,
								"phone" => $phonenumber,
								"created" => time()));
		$secureToken = crypto::encryptText($rawToken,CONFIG_EMAIL_OPTINKEY);
		return $secureToken;
	}

	/* sends a HTML e-mail message to the recipient passed using 
		the subject and HTML body provided as parameter. Other 
		settings are taken from the site configuration */
	private function sendEmailMessage($recipient,$subject,$body){
		$email_header = "From: ".CONFIG_EMAIL_SENDER."\r\n"
					."Reply-To: ".CONFIG_EMAIL_SENDER."\r\n"
					."MIME-Version: 1.0\r\n"
					."Content-Type: text/html; charset=utf8\r\n"
					."User-Agent: ".CONFIG_EMAIL_AGENT."\r\n"
					."X-Mailer: ".CONFIG_EMAIL_AGENT."\r\n";

		/* send the email with the data provided */
		mail($recipient,$subject,$body,$email_header);
	}
}
?>